%==========================================================================
%=  This file is part of the Sound Restoration Project
%=  (c) Copyright Industrial Mathematics Institute
%=                University of South Carolina, Department of Mathematics
%=  ALL RIGHTS RESERVED
%=
%=  Author: Borislav Karaivanov
%==========================================================================

%==========================================================================
% List of the files on which this procedure depends:
%
% any on which the function passed by the handle "fitFunctHandle" depends
%
%==========================================================================

%==========================================================================
% The function "fitReduceFitSignal" repeatedly fits and reduces the length
% of a given signal until the best (in uniform metric sense) fit within an
% allowed amount of reduction is attained. Signal is fitted with a
% specified method implemented elsewhere. Signal reduction consists of
% removing segments of samples from either of its ends. So, the given
% signal is fit and largest in absolute value difference between the fit
% and the signal is found. If that difference occurs sufficiently close to
% the beginning or the end of the signal, then the signal is reduced by
% removing its portion from the sample where the said difference is
% attained to the signal's closer end. The same steps are repeated with the
% reduced signal while the cumulative length of the removed segments
% remains smaller than a specified amount.
% INPUT: "signalArr" is a vector holding the signal to be fitted.
% "fitFunctHandle" is a handle to a function implementing the fitting
% method to be used.
% "allowedCut" is an optional positive integer specifying the maximal
% allowed cumulative length of the segments removed form both ends of the
% signal.
% OUTPUT: "fitArr" returns a vector of length not greater than that of the
% original signal holding the best fit to the reduced version of the given
% signal.
% "leftCut" returns the number of samples removed at the beginning of the
% given signal.
% "rightCut" returns the number of samples removed at the end of the given
% signal.
% "maxDiff" returns the largest absolute difference between the reduced
% signal and its fit.
%==========================================================================
function [fitArr, leftCut, rightCut, maxDiff] = ...
    fitReduceFitSignal(signalArr, fitFunctHandle, allowedCut)

% Initialize the amounts of samples removed at the beginning and the end of
% the given signal.
leftCut = 0;
rightCut = 0;

while true
    
    % Fit the current portion of the signal.
    fitArr = fitFunctHandle(signalArr);
    
    % Find the largest uniform difference between the reduced signal and
    % its fit.
    [maxDiff, maxDiffInd] = max(abs(fitArr - signalArr));
    
    % Check if the largest absolute difference can be reduced by removing a 
    % segment at the beginning of the current signal without exceeding the
    % maximal allowed amount of cuts.
    if (maxDiffInd <= allowedCut)
        leftCut = leftCut + maxDiffInd;
        allowedCut = allowedCut - maxDiffInd;
        signalArr = signalArr((maxDiffInd + 1):end);
        continue;
    end
    
    % Check if the largest absolute difference can be reduced by removing a 
    % segment at the end of the current signal without exceeding the
    % maximal allowed amount of cuts.
    currCut = numel(signalArr) - maxDiffInd + 1;
    if (currCut <= allowedCut)
        rightCut = rightCut + currCut;
        allowedCut = allowedCut - currCut;
        signalArr = signalArr(1:(maxDiffInd - 1));
    else
        return;
    end
end

% end of the function "fitReduceFitSignal"
